package learn.up.java.algorithm;

import org.junit.Test;

/**
 *位操作符  与&  或 |   异或^  非 ~
 * @author NANUTO
 * @date 2017年11月21日 上午12:07:50
 */
public class LogicAlgorithm {

	@Test
	public void tset1() {
		/*
		 * 按位与 &,两个操作数中二进制位都为1，结果才为1，否则结果为0
		 * 5转换为二进制：0000 0000 0000 0000 0000 0000 0000 0101
		 * 3转换为二进制：0000 0000 0000 0000 0000 0000 0000 0011
		 *      				    0000 0000 0000 0000 0000 0000 0000 0001
		 *      1. 清零，任何数 & 0  都将变为0
		 *      2.寻找某数的低几位数，例如，要找 1001 0111 的低四位数，
		 *      只需要 1001 0111 & 0000 1111  就可以得到低四位数为 0111，同理低5位数也一样
		 */
		System.out.println(5 & 3);   //  为1
		/*
		 * 当n一定是2的幂次时， 5 & (n - 1)  等于 5 % n
		 * 2^n转换成二进制就是1+n个0，减1之后就是0+n个1，如16 -> 10000，15 -> 01111，
		 * 那根据&位运算的规则，都为1(真)时，才为1，那0≤运算后的结果≤15，假设h <= 15，
		 * 那么运算后的结果就是h本身，h >15，运算后的结果就是最后4位二进制做&运算后的
		 * 值，最终，就是%运算后的余数，
		 */
		System.out.println(5 & (8 - 1));  //5
		System.out.println(5 % 8);  //5
	}
	
	@Test
	public void test2() {
		/*
		 * 按位或( | ),只要有一个是1，那么结果的第n为也为1，否则为0
		 * 5转换为二进制：0000 0000 0000 0000 0000 0000 0000 0101
		 * 3转换为二进制：0000 0000 0000 0000 0000 0000 0000 0011
		 * 7转换为二进制：0000 0000 0000 0000 0000 0000 0000 0111
		 * 用途1：把某二进制数某些位置位1，只要把该数 xxxx xxxx | xxxx 1111,  这里就
		 * 能把该数的低四位置位1
		 */
		System.out.println(5 | 3);  //7
	}
	
	@Test
	public void test3() {
		/*
		 * 按位异或( ^ )，第一个操作数的的第n位与第二个操作数的第n位 相反，那么结果的第n为也为1，否则为0
		 * 5转换为二进制：0000 0000 0000 0000 0000 0000 0000 0101
		 * 3转换为二进制：0000 0000 0000 0000 0000 0000 0000 0011
		 * 6转换为二进制：0000 0000 0000 0000 0000 0000 0000 0110
		 * 其实java中的异或运算法则完全遵守数学中的计算法则：
	①    a ^ a =0
	②    a ^ b =b ^ a
	③    a ^b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
	④    d = a ^b ^ c 可以推出 a = d ^ b ^ c.
	⑤    a ^ b ^a = b.
		 */
		System.out.println(5 ^ 3); //6
		/*
		 * 	3.      不用临时变量交换两个数,
		 * 可以发现，异或0具有保持的特点，而异或1具有翻转的特点。使用这些特点可以进行取数的操作。
		 * 任何数 X ^ 0 = X
		 */
		int a = 5, b = 6;
		a = a ^ b;
		b = b ^ a;		//=b ^ (a ^ b) = a
		a = a ^ b;  //
		System.out.println(a + "  ;  "+b);
		/*
		 * 4.使某些位数反转，例如：X = 0101 0011，要使X的低四位反转，只需要
		 * X ^ 0000 1111
		 */
	}
	
	@Test
	public void test4() {
		/*
		 * 按位非( ~ )，位非是一元操作符。操作数的第n位为1，那么结果的第n位为0，反之
		 *  5转换为二进制：0000 0000 0000 0000 0000 0000 0000 0101
		 * -6转换为二进制：1111 1111 1111 1111 1111 1111 1111 1010
		 */
		System.out.println(~ 5);  //-6
	}
	
}
